package com.zrx.govern.component.easyexcel.starter.aop;

import com.zrx.govern.component.easyexcel.starter.Exception.ExcelModelOnlyOneOperationException;
import com.zrx.govern.component.easyexcel.starter.annotation.ExcelException;
import com.zrx.govern.component.easyexcel.starter.constants.RedisConstants;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author zhangxiaowei
 * @desc 声明@Order(-1),表示当前自定义切面先执行，比如比@Transactional先执行
 */
@Aspect
@RequiredArgsConstructor
@Component
@Order(-1)
public class ExcelExceptionAspect {
    private final RedisTemplate redisTemplate;

    /**
     * 监测导入导出任务是否异常，如果发生异常，将导入导出任务key删除
     * @param point
     * @param excelException
     * @return: void
     * @author zhangxiaowei
     **/
    @AfterThrowing(throwing = "ex",value = "@annotation(excelException)")
    public void afterThrowing(JoinPoint point, Throwable ex,ExcelException excelException) {
        /*如果异常为允许一人操作的自定义异常,跳过，不删除task key*/
        if (ex instanceof ExcelModelOnlyOneOperationException) {
            return;
        }
        MethodSignature ms = (MethodSignature) point.getSignature();
        Method method = ms.getMethod();
        ExcelException exception = method.getAnnotation(ExcelException.class);
        String modelSpel = exception.model();
        //参数对象
        Object[] args = point.getArgs();
        String model = "";
        String[] parameterNames = new LocalVariableTableParameterNameDiscoverer().getParameterNames(method);

        //SPEL上下文
        StandardEvaluationContext context = new StandardEvaluationContext();
        //把方法参数放入SPEL上下文中
        for (int i = 0; i < parameterNames.length; i++) {
            context.setVariable(parameterNames[i], args[i]);
        }
        // 使用变量方式传入业务动态数据
        if(modelSpel.matches("^#.*.$")) {
            //使用SPEL进行key的解析
            ExpressionParser parser = new SpelExpressionParser();
            model = parser.parseExpression(modelSpel).getValue(context, String.class);
        }
        if (StringUtils.isBlank(model)) {
            throw new RuntimeException("model值获取为空!");
        }
        String key = RedisConstants.EXCEL_TASK + model;
        if (redisTemplate.hasKey(key)) {
            redisTemplate.delete(key);
        }

    }

}
